﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BusinessLogic;
using System.Data;
using System.Text;

namespace SEP.Admin
{
    public partial class ServiceReportPage : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if(IsPostBack)
            {
                //postback
            }
            else
            {
                //not a postback
                string id = string.Empty;

                if(Request.QueryString["ID"] != null)
                {
                    id = Request.QueryString["ID"].ToString();

                }
                else if(Request.QueryString["constituentID"] != null)
                {
                    string constituentID = Request.QueryString["constituentID"].ToString();

                    //if(!string.IsNullOrWhiteSpace(constituentID))
                    //{
                    //    CreateConstituentServiceReport(new Guid(constituentID));
                    //}
                }
                
                if (Request.QueryString["archived"] != null)
                {
                    if (Request.QueryString["archived"].Equals(bool.TrueString))
                    {
                        Response.Redirect(string.Format("~/Admin/ServiceReportViewDetail.aspx?id={0}", id));
                    }
                }

                if(!string.IsNullOrWhiteSpace(id))
                {
                    LoadServiceReport(new Guid(id));
                }
                
                BindData();
            }

            //used for modal searches
            ClientScript.RegisterStartupScript(this.GetType(), "InstrumentModalPopup", "function showInstrumentModal() { $find('ShowInstrumentModal').show(); }", true);
            ClientScript.RegisterStartupScript(this.GetType(), "PartModalPopup", "function showPartModal() { $find('ShowPartModal').show(); }", true);
        }

        private void BindData()
        {
            BindSearchGridView(grvInstrumentSearch, Instrument.SearchAll);
            BindSearchGridView(grvPartSearch, Part.SearchAll);            
        }

        private Guid GetJobID()
        {
            Guid jobID = Guid.Empty;

            if (Request.QueryString["jobID"] != null)
            {
                jobID = new Guid(Request.QueryString["jobID"].ToString());
            }

            return jobID;
        }

        private void BindSearchGridView(GridView grv, Func<DataTable> searchAllMethod)
        {            
            string searchDataTable = grv.ID + "SEARCHDATATABLE";

            DataTable dt = (DataTable)Session[searchDataTable];

            if(dt == null)
            {
                dt = searchAllMethod();
                Session[searchDataTable] = dt;
            }   

            grv.DataSource = dt;
            grv.DataBind();
        }

        private void LoadServiceReport(Guid serviceReportID)
        {
            ServiceReport sr = ServiceReport.GetByID(serviceReportID);

            Session["PARTS"] = sr.Parts;
            Session["SERVICETOTALS"] = sr.Totals;

            if(sr.Instrument != null)
            {
                txtManufacturer.Text = sr.Instrument.ManufacturerType.Description;
                txtInstrumentType.Text = sr.Instrument.InstrumentType.Description;
                txtModel.Text = sr.Instrument.Model;
                txtSerialNumber.Text = sr.Instrument.SerialNumber;
                txtUnitNumber.Text = sr.Instrument.UnitNumber;
            }

            txtPONumber.Text = sr.PONumber;
            txtServicePerformed.Text = sr.ServicePerformed;
            txtServiceRequired.Text = sr.ServiceRequired;

            grvParts.DataSource = sr.Parts;
            grvParts.DataBind();

            grvTotals.DataSource = sr.Totals;
            grvTotals.DataBind();

            UpdateTotals();
        }
                
        protected void grvInstrumentSearch_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            PageIndexChanging(grvInstrumentSearch, btnInstrumentSearch_Click, sender, e);
        }

        protected void grvPartSearch_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            PageIndexChanging(grvPartSearch, btnPartSearch_Click, sender, e);
        }

        private void PageIndexChanging(GridView grv, Action<object, GridViewPageEventArgs> Search_Click, object sender, GridViewPageEventArgs e)
        {
            string searchDataTableLocation = grv.ID + "SEARCHDATATABLE";
            string filteredDataTableLocation = grv.ID + "FILTEREDDATATABLE";

            DataTable dt = Session[searchDataTableLocation] as DataTable;

            if (Session[filteredDataTableLocation] != null)
            {
                dt = Session[filteredDataTableLocation] as DataTable;
            }

            grv.DataSource = dt;
            grv.PageIndex = e.NewPageIndex;
            grv.DataBind();

            Search_Click(sender, e);
        }

        protected void grvInstrumentSearch_OnSorting(object sender, GridViewSortEventArgs e)
        {
            OnSorting(e, grvInstrumentSearch, modalInstrumentSearch);
        }

        protected void grvPartSearch_OnSorting(object sender, GridViewSortEventArgs e)
        {
            OnSorting(e, grvPartSearch, modalPartSearch);
        }

        private void OnSorting(GridViewSortEventArgs e, GridView grv, AjaxControlToolkit.ModalPopupExtender extender)
        {
            string searchDataTableLocation = grv.ID + "SEARCHDATATABLE";
            string filteredDataTableLocation = grv.ID + "FILTEREDDATATABLE";

            DataTable dt = Session[searchDataTableLocation] as DataTable;

            if (Session[filteredDataTableLocation] != null)
            {
                dt = Session[filteredDataTableLocation] as DataTable;
            }

            if (dt != null)
            {
                //Sort the data.
                dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression, grv.ID);
                grv.DataSource = dt;
                grv.DataBind();

                Session[searchDataTableLocation] = dt;
                Session[filteredDataTableLocation] = dt;
            }
            //sorting closes the modal popup.  re-display it.
            extender.Show();
        }

        protected void grvInstrumentSearch_OnSelectedIndexChanging(object sender, GridViewSelectEventArgs e)
        {
            GridViewRow selectedRow = grvInstrumentSearch.Rows[e.NewSelectedIndex];

            if (selectedRow != null)
            {
                txtInstrumentType.Text = CleanString(selectedRow.Cells[1].Text);
                txtManufacturer.Text = CleanString(selectedRow.Cells[2].Text);
                txtModel.Text = CleanString(selectedRow.Cells[3].Text);
            }
        }

        protected void grvPartSearch_OnSelectedIndexChanging(object sender, GridViewSelectEventArgs e)
        {
            GridViewRow selectedRow = grvPartSearch.Rows[e.NewSelectedIndex];

            if (selectedRow != null)
            {
                txtPartDescription.Text = CleanString(selectedRow.Cells[1].Text);
                txtPartNumber.Text = CleanString(selectedRow.Cells[2].Text);
                txtPartPrice.Text = CleanString(selectedRow.Cells[3].Text);
                
                HiddenField hfPartSearchID = (HiddenField)selectedRow.FindControl("hfPartSearchID");

                if(hfPartSearchID != null)
                {
                    hfPartID.Value = hfPartSearchID.Value;
                }
            }
        }

        private string CleanString(string input)
        {
            string result;

            result = Server.HtmlDecode(input); // input.Replace("&nbsp;", "").Replace("&amp;", "&").Replace("&#39;", "'");

            return result;
        }

        private string GetSortDirection(string column, string gridViewName)
        {
            string sortExpressionName = gridViewName + "SortExpression";
            string sortDirectionName = gridViewName + "SortDirection";

            // By default, set the sort direction to ascending.
            string sortDirection = "ASC";

            // Retrieve the last column that was sorted.
            string sortExpression = Session[sortExpressionName] as string;

            if (sortExpression != null)
            {
                // Check if the same column is being sorted.
                // Otherwise, the default value can be returned.
                if (sortExpression == column)
                {
                    string lastDirection = Session[sortDirectionName] as string;
                    if ((lastDirection != null) && (lastDirection == "ASC"))
                    {
                        sortDirection = "DESC";
                    }
                }
            }

            // Save new values in ViewState.
            Session[sortDirectionName] = sortDirection;
            Session[sortExpressionName] = column;

            return sortDirection;
        }

        private void SearchGridView(GridView grv, string searchCriteria, Action<object, EventArgs> Search_Click, object sender, EventArgs e)
        {
            if(!string.IsNullOrWhiteSpace(searchCriteria))
            {
                string searchDataTable = grv.ID + "SEARCHDATATABLE";
                string filteredDataTable = grv.ID + "FILTEREDDATATABLE";

                DataTable dt = Session[searchDataTable] as DataTable;

                if (dt != null)
                {
                    DataRow[] rows = dt.Select(searchCriteria);
                    DataTable filtered = dt.Copy();

                    filtered.Rows.Clear();

                    foreach (DataRow r in rows)
                    {
                        filtered.ImportRow(r);
                    }

                    Session[filteredDataTable] = filtered;

                    grv.DataSource = filtered;
                    grv.DataBind();
                }

                Search_Click(sender, e);            
            }
        }

        protected void btnInstrumentSearch_Click(object sender, EventArgs e)
        {
            pnlInstrumentSearch.Visible = true;
            modalInstrumentSearch.Show();
        }

        protected void btnInstrumentSubmit_Click(object sender, EventArgs e)
        {
            string text = txtInstrumentSearch.Text;
            string searchString = "INSTRUMENTTYPE like '%" + text + "%' or MANUFACTURER like '%" + text + "%' or MODEL like '%" + text + "%'";

            SearchGridView(grvInstrumentSearch, searchString, btnInstrumentSearch_Click, sender, e);   
        }

        protected void btnPartSearch_Click(object sender, EventArgs e)
        {
            pnlPartSearch.Visible = true;
            modalPartSearch.Show();
        }

        protected void btnPartSubmit_Click(object sender, EventArgs e)
        {
            string text = txtPartSearch.Text;
            string searchString = "DESCRIPTION like '%" + text + "%' or PARTNUMBER like '%" + text + "%'";

            SearchGridView(grvPartSearch, searchString, btnPartSearch_Click, sender, e);   
        }

        protected void btnPartAdd_Click(object sender, EventArgs e)
        {
            PartList parts = new PartList();

            if(Session["PARTS"] != null)
            {
                parts = (PartList)Session["PARTS"];
            }

            Part p = new Part();
            p.Description = txtPartDescription.Text;
            p.Number = txtPartNumber.Text;

            string temp = txtPartPrice.Text.Replace("$", "").Replace(",", "");
            decimal price;

            if (Decimal.TryParse(temp, out price))
            {
                p.Price = price;
            }

            p.Quantity = (string.IsNullOrWhiteSpace(txtPartQuantity.Text) ? 0 : Convert.ToInt32(txtPartQuantity.Text));            
            p.ID = (string.IsNullOrWhiteSpace(hfPartID.Value) ? Guid.NewGuid() : new Guid(hfPartID.Value));            
            parts.Add(p);
            
            Session["PARTS"] = parts;

            grvParts.DataSource = parts;
            grvParts.DataBind();

            UpdateTotals();

            txtPartQuantity.Text = "";
            txtPartPrice.Text = "";
            txtPartDescription.Text = "";
            txtPartNumber.Text = "";
        }

        protected void udpTotals_Load(object sender, EventArgs e)
        {
            UpdateTotals();
        }
                
        protected void grvParts_DeleteRecord(object sender, GridViewDeleteEventArgs e)
        {
            Guid id = new Guid(grvParts.DataKeys[e.RowIndex].Value.ToString());

            if(id != Guid.Empty)
            {
                PartList parts = new PartList();

                if (Session["PARTS"] != null)
                {
                    parts = (PartList)Session["PARTS"];

                    IEnumerable<Part> partsToRemove = from p in parts.Cast<Part>()
                                                where p.ID == id
                                                select p;

                    foreach (var item in partsToRemove.ToList())
                    {
                        parts.Remove(item);
                    }

                    Session["PARTS"] = parts;

                    grvParts.DataSource = parts;
                    grvParts.DataBind();

                    UpdateTotals();
                }
            }
        }

        protected void grvParts_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            RowDataBound(e, "part");
        }

        protected void grvTotals_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            RowDataBound(e, "service total");
        }

        protected void grvTotals_DeleteRecord(object sender, GridViewDeleteEventArgs e)
        {
            Guid id = new Guid(grvTotals.DataKeys[e.RowIndex].Value.ToString());

            if (id != Guid.Empty)
            {
                ServiceTotalList serviceTotals = new ServiceTotalList();

                if(Session["SERVICETOTALS"] != null)
                {
                    serviceTotals = (ServiceTotalList)Session["SERVICETOTALS"];

                    IEnumerable<ServiceTotal> serviceTotalsToRemove = from st in serviceTotals.Cast<ServiceTotal>()
                                                where st.ID == id
                                                select st;
                                                                    
                    foreach (var item in serviceTotalsToRemove.ToList())
                    {
                        serviceTotals.Remove(item);
                    }                       

                    Session["SERVICETOTALS"] = serviceTotals;

                    grvTotals.DataSource = serviceTotals;
                    grvTotals.DataBind();
                    
                    UpdateTotals();
                }                    
            }            
        }

        #region Helper methods
        /// <summary>
        /// Adds onclick to the linkbutton in the gridview.
        /// </summary>
        /// <param name="e"></param>
        /// <param name="deleteWhat">You are about to delete this [deleteWhat]?</param>
        private void RowDataBound(GridViewRowEventArgs e, string deleteWhat)
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                LinkButton l = (LinkButton)e.Row.FindControl("LinkButton1");
                l.Attributes.Add("onclick", string.Format("javascript:return confirm('You are about to delete this {0}?')", deleteWhat.Trim()));
            }
        }
        #endregion

        /// <summary>
        /// Updates all totals on the page.
        /// Calls UpdateGrandTotal() at the end of updating all previous totals.
        /// </summary>
        private void UpdateTotals()
        {
            decimal labor = 0.00M; 
            decimal travel = 0.00M;
            decimal mileage = 0.00M;
            decimal other = 0.00M; 
            decimal parts = 0.00M;
            StringBuilder others = new StringBuilder();

            foreach(GridViewRow row in grvTotals.Rows)
            {
                if(row.FindControl("litLabor") != null)
                {
                    labor += GetDecimalFromLiteral((Literal)row.FindControl("litLabor"));
                }
                if (row.FindControl("litTravel") != null)
                {
                    travel += GetDecimalFromLiteral((Literal)row.FindControl("litTravel"));
                }
                if (row.FindControl("litMileage") != null)
                {
                    mileage += GetDecimalFromLiteral((Literal)row.FindControl("litMileage"));
                }
                if (row.FindControl("litOther") != null)
                {
                    other += GetDecimalFromLiteral((Literal)row.FindControl("litOther"));
                }
                if(row.FindControl("litOtherDescription") != null)
                {
                    others.AppendLine(string.Concat(((Literal)row.FindControl("litOtherDescription")).Text, ";"));
                }
            }

            foreach (GridViewRow row in grvParts.Rows)
            {
                if (row.FindControl("litPartTotal") != null)
                {
                    parts += GetDecimalFromLiteral((Literal)row.FindControl("litPartTotal"));
                }
            }

            litTotalLabor.Text = labor.ToString();
            litTotalTravel.Text = travel.ToString();
            litTotalMileage.Text = mileage.ToString();
            litTotalOther.Text = other.ToString();
            litTotalParts.Text = parts.ToString();
            litOtherDescriptions.Text = others.ToString();
        }
                
        private decimal GetDecimalFromLiteral(Literal l)
        {
            return GetDecimalFromString(l.Text);
        }

        private decimal GetDecimalFromTextBox(TextBox t)
        {
            return GetDecimalFromString(t.Text);
        }

        private decimal GetDecimalFromString(string s)
        {
            s = s.Replace("$", "").Replace(",", "");

            decimal result = 0.00M;

            if(Decimal.TryParse(s, out result))
            {
                return result;
            }
            else
            {
                return 0;
            }
        }

        protected void btnAddTotals_Click(object sender, EventArgs e)
        {
            ServiceTotalList serviceTotals = new ServiceTotalList();

            if(Session["SERVICETOTALS"] != null)
            {
                serviceTotals = (ServiceTotalList)Session["SERVICETOTALS"];
            }

            ServiceTotal total = new ServiceTotal();
            total.ID = Guid.NewGuid();
            var date = DateTime.Now;

            if(DateTime.TryParse(txtDate.Text, out date))
            {
                total.Date = date;
            }
                        
            total.Labor = GetDecimalFromString(txtLabor.Text);
            total.Mileage = GetDecimalFromString(txtMileage.Text);
            total.Other = GetDecimalFromString(txtOther.Text);
            total.Travel = GetDecimalFromString(txtTravel.Text);
            total.OtherDescription = txtOtherDescription.Text;

            serviceTotals.Add(total);

            grvTotals.DataSource = serviceTotals;
            grvTotals.DataBind();

            UpdateTotals();

            Session["SERVICETOTALS"] = serviceTotals;

            txtDate.Text = "";
            txtLabor.Text = "";
            txtMileage.Text = "";
            txtOther.Text = "";
            txtTravel.Text = "";
            txtOtherDescription.Text = "";
        }

        protected void btnSave_OnClick(object sender, EventArgs e)
        {
            ServiceReport report = CreateServiceReport();

            if(report.ID != Guid.Empty)
            {                
                Response.Redirect(string.Format("~/Admin/ServiceReportView.aspx?jobid={0}", report.JobID));
            }
        }

        private ServiceReport GetCurrentServiceReport()
        {
            ServiceReport report = new ServiceReport();
            report.JobID = GetJobID();

            //service totals
            if (Session["SERVICETOTALS"] != null)
            {
                report.Totals = (ServiceTotalList)Session["SERVICETOTALS"];
            }
            else
            {
                report.Totals = new ServiceTotalList();
            }

            //parts
            if (Session["PARTS"] != null)
            {
                report.Parts = (PartList)Session["PARTS"];
            }
            else
            {
                report.Parts = new PartList();
            }

            //instrument
            Instrument instrument = new Instrument();
            instrument.SerialNumber = txtSerialNumber.Text;
            instrument.UnitNumber = txtUnitNumber.Text;
            instrument.Model = txtModel.Text;

            InstrumentType instrumentType = new InstrumentType();
            instrumentType.Description = txtInstrumentType.Text;
            instrument.InstrumentType = instrumentType;

            ManufacturerType manufacturerType = new ManufacturerType();
            manufacturerType.Description = txtManufacturer.Text;
            instrument.ManufacturerType = manufacturerType;

            report.Instrument = instrument;
            report.PONumber = txtPONumber.Text;
            report.ServicePerformed = txtServicePerformed.Text;
            report.ServiceRequired = txtServiceRequired.Text;
            
            //is this an update?
            if (Request.QueryString["ID"] != null)
            {
                string id = Request.QueryString["ID"].ToString();

                if (!string.IsNullOrWhiteSpace(id))
                {
                    Guid reportID;

                    if (Guid.TryParse(id, out reportID))
                    {
                        report.ID = reportID;
                    }
                }
            }

            return report;
        }

        public void ClearServiceReportSessions()
        {
            //clear all sessions set on this service report
            //in case the user comes back to do another service report 
            //after completing one there wont be old values sitting around
            Session["SERVICETOTALS"] = null;
            Session["PARTS"] = null;
        }

        private ServiceReport CreateServiceReport()
        {
            ServiceReport report = GetCurrentServiceReport();
            
            if (report.Create())
            {
                ClearServiceReportSessions();
            }
            else
            {
                report.ID = Guid.Empty;
            }
            
            return report;
        }

        protected void btnSendToIan_Click(object sender, EventArgs e)
        {
            ServiceReport report = CreateServiceReport();
            
            if (report.ID != Guid.Empty)
            {
                ServiceReport.SendToIan(report.ID);
                Response.Redirect(string.Format("~/Admin/ServiceReportView.aspx?jobid={0}", report.JobID));
            }
        }

        protected void btnSendToJenny_Click(object sender, EventArgs e)
        {
            ServiceReport report = CreateServiceReport();

            if (report.ID != Guid.Empty)
            {
                ServiceReport.SendToJenny(report.ID);
                Response.Redirect(string.Format("~/Admin/ServiceReportView.aspx?jobid={0}", report.JobID));
            }
        }      
    }
}
